package com.sunrise.xdoc.view.catalog;

import java.io.Serializable;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import org.primefaces.component.datatable.DataTable;
import org.primefaces.context.RequestContext;
import org.primefaces.event.CellEditEvent;

import com.sunrise.xdoc.dto.LoaiSanPhamDTO;
import com.sunrise.xdoc.entity.catalog.SanPham;
import com.sunrise.xdoc.entity.order.ChiTietDonHang;
import com.sunrise.xdoc.entity.order.DinhMuc;
import com.sunrise.xdoc.entity.order.DonHang;
import com.sunrise.xdoc.event.EventData;
import com.sunrise.xdoc.event.EventNameConstants;
import com.sunrise.xdoc.event.ListenerMethod;
import com.sunrise.xdoc.service.ICatalogService;
import com.sunrise.xdoc.service.IOrderService;

@ManagedBean
@SessionScoped
public class BanHang implements Serializable {
	private static final String CHI_TIET_TABLE_VIEW_ID = "chiTietTableFormId:chiTietTableId";

	private static final long serialVersionUID = -3354970710973211655L;

	@ManagedProperty(value = "#{catalogService}")
	private ICatalogService catalogService;

	@ManagedProperty(value = "#{orderService}")
	private IOrderService orderService;

	private List<LoaiSanPhamDTO> loaiSanPhams;
	private DonHang donHang;
	private ChiTietDonHang selectedCtDonHang;

	@PostConstruct
	public void init() {
		setLoaiSanPhams(catalogService.getLoaiSanPhamOfSanPhamDuocBan());
	}

	/**
	 * Add sản phẩm vào table chi tiết đơn hàng. Nếu sản phẩm đã có
	 * trong table, tăng số lượng lên 1. Nếu chưa có, thêm 1 chiTiet vào
	 * đơn hàng và tạo 1 dòng mới. <br/>
	 * Giảm định mức còn lại của sản phẩm
	 * 
	 * @param dm
	 *            dinhMuc entity
	 */
	public void addSanPham(DinhMuc dm) {
		SanPham sp = dm.getSanPham();
		boolean exist = false;
		for (ChiTietDonHang ctDonHang : donHang.getChiTietDonHangs()) {
			if (sp.getId().equals(ctDonHang.getSanPham().getId())) {
				ctDonHang.setSoLuong(ctDonHang.getSoLuong() + 1);
				selectedCtDonHang = ctDonHang;
				exist = true;
			}
		}
		if (!exist) {
			// Thêm 1 chi tiết vào đơn hàng
			ChiTietDonHang ctDonHang = new ChiTietDonHang();
			ctDonHang.setDonGia(sp.getDonGia());
			ctDonHang.setSanPham(sp);
			ctDonHang.setSoLuong(1);
			ctDonHang.setDonHang(getDonHang());
			selectedCtDonHang = ctDonHang;
			getDonHang().getChiTietDonHangs().add(ctDonHang);
		}

		getDonHang().setTongGiaSanPham(getDonHang().getTongGiaSanPham() + sp.getDonGia());
		orderService.saveOrUpdateDonHang(donHang);

		// Giảm định mức còn lại
		dm.setConLai(dm.getConLai() - 1);
		orderService.saveOrUpdateDinhMuc(dm);
	}

	public void updateDonHang() {
		// Khi chi tiết đơn hàng update -> update toàn bộ đơn hàng
		long tongTienSp = 0L;
		for (ChiTietDonHang ct : donHang.getChiTietDonHangs()) {
			tongTienSp += ct.getDonGia() * ct.getSoLuong();
		}
		donHang.setTongGiaSanPham(tongTienSp);
		orderService.saveOrUpdateDonHang(donHang);
	}

	@ListenerMethod(acceptedEvents = { "saveOrUpdateSanPham", "deleteSanPham", "saveOrUpdateDinhMuc", "deleteDinhMuc",
			EventNameConstants.ACTIVE_SP })
	public void processEvent(EventData eventData, String eventName) {
		// TODO this can be optimize by just update data on view, no need to
		// re-init all data
		init();
	}

	public void reset() {
		RequestContext.getCurrentInstance().reset("chiTietTableFormId");
	}

	public void soLuongEdit(CellEditEvent event) {
		int oldSL = (int) event.getOldValue();
		int newSL = (int) event.getNewValue();
		DataTable dataTable = (DataTable) event.getSource();

		// Update định mức
		ChiTietDonHang chiTietDonHang = (ChiTietDonHang) dataTable.getRowData();
		updateDinhMuc(oldSL, newSL, chiTietDonHang);

		//
		updateDonHang();

		// Update đơn giá & thành tiền on view
		updateChiTietDonHangRowView(event.getRowIndex());
	}

	private void updateDinhMuc(int oldSL, int newSL, ChiTietDonHang chiTietDonHang) {
		SanPham spEdited = chiTietDonHang.getSanPham();
		for (LoaiSanPhamDTO lsp : loaiSanPhams) {
			boolean isFound = false;
			for (DinhMuc dm : lsp.getDinhMucs()) {
				if (spEdited.equals(dm.getSanPham())) {
					int oldConLai = dm.getConLai();
					int newConLai = oldConLai - (newSL - oldSL);
					if (newConLai < 0) {
						FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Cảnh báo: Số lượng '"
								+ spEdited.getName() + "' còn lại không đủ.", "");
						FacesContext.getCurrentInstance().addMessage(null, msg);
					}
					dm.setConLai(newConLai);
					orderService.saveOrUpdateDinhMuc(dm);
					isFound = true;
					break;
				}
			}
			if (isFound) {
				break;
			}
		}
	}

	private void updateChiTietDonHangRowView(int rowIndex) {
		RequestContext.getCurrentInstance().update(CHI_TIET_TABLE_VIEW_ID + ":" + rowIndex + ":soLuongId");
		RequestContext.getCurrentInstance().update(CHI_TIET_TABLE_VIEW_ID + ":" + rowIndex + ":donGiaId");
		RequestContext.getCurrentInstance().update(CHI_TIET_TABLE_VIEW_ID + ":" + rowIndex + ":thanhTienId");
	}

	public void onRowSelected() {
		// Vì onRowSelect set immediate=true -> chưa binding vào
		// selectedCtDonHang
		if (selectedCtDonHang == null) {
			RequestContext.getCurrentInstance().update("tongCongFormPanelId");
		}
	}

	public String troVeDanhSachBan() {
		selectedCtDonHang = null;
		return "/pages/config/danhSachBanKhuVuc";
	}

	/**
	 * Khi keypad được click, update số lượng của chi tiết đơn hàng đang được
	 * chọn.
	 * 
	 * @param keyValue
	 *            the keypad value: 0, 00, 000, 1, 2, 3, 4, 5, 6, 7, 8, 9, Back,
	 *            Delete
	 */
	public void onClickKeypad(String keyValue) {
		if (selectedCtDonHang == null) {
			return;
		}

		String oldValue = String.valueOf(selectedCtDonHang.getSoLuong());
		if (keyValue.equals("Back")) {
			String newValue = oldValue.substring(0, oldValue.length() - 1);
			selectedCtDonHang.setSoLuong(newValue.isEmpty() ? 0 : Integer.valueOf(newValue));
			updateDinhMuc(Integer.valueOf(oldValue), Integer.valueOf(newValue), selectedCtDonHang);
			// Update on view
			updateChiTietDonHangRowView(donHang.getChiTietDonHangs().indexOf(selectedCtDonHang));

		} else if (keyValue.equals("Delete")) {
			donHang.getChiTietDonHangs().remove(selectedCtDonHang);
			selectedCtDonHang = null;
			RequestContext.getCurrentInstance().update(CHI_TIET_TABLE_VIEW_ID);
		} else {
			String newValue = oldValue + keyValue;
			if (newValue.length() > 4) {
				FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Số lượng không được lớn hơn 9999", "");
				FacesContext.getCurrentInstance().addMessage(null, msg);
				return;
			}
			selectedCtDonHang.setSoLuong(newValue.isEmpty() ? 0 : Integer.valueOf(newValue));
			updateDinhMuc(Integer.valueOf(oldValue), Integer.valueOf(newValue), selectedCtDonHang);
			// Update on view
			updateChiTietDonHangRowView(donHang.getChiTietDonHangs().indexOf(selectedCtDonHang));
		}

		updateDonHang();
	}

	public List<LoaiSanPhamDTO> getLoaiSanPhams() {
		return loaiSanPhams;
	}

	public void setLoaiSanPhams(List<LoaiSanPhamDTO> loaiSanPhams) {
		this.loaiSanPhams = loaiSanPhams;
	}

	public DonHang getDonHang() {
		return donHang;
	}

	public boolean getRendered() {
		return donHang != null;
	}

	public void setDonHang(DonHang donHang) {
		this.donHang = donHang;
	}

	public ICatalogService getCatalogService() {
		return catalogService;
	}

	public void setCatalogService(ICatalogService catalogService) {
		this.catalogService = catalogService;
	}

	public IOrderService getOrderService() {
		return orderService;
	}

	public void setOrderService(IOrderService orderService) {
		this.orderService = orderService;
	}

	public ChiTietDonHang getSelectedCtDonHang() {
		return selectedCtDonHang;
	}

	public void setSelectedCtDonHang(ChiTietDonHang selectedCtDonHang) {
		this.selectedCtDonHang = selectedCtDonHang;
	}
}
